﻿#pragma once
#include <iostream>
#include <functional>

namespace PtrMudule
{
	struct Date
	{
		Date(int year,int month,int day)
			:_year(year),_month(month),_day(day)
		{
		}
		~Date()
		{
			std::cout << "~Date()" << std::endl;
		}
	private:
		int _year;
		int _month;
		int _day;
	};
	template<typename T>
	class auto_ptr
	{
	public:
		auto_ptr(T* ptr)
			:_ptr(ptr)
		{

		}
		~auto_ptr()
		{
			if (_ptr)
				delete _ptr;
			std::cout << "~auto_ptr()" << std::endl;
		}

		//假拷贝
		auto_ptr(auto_ptr<T>& ap)
			:_ptr(ap._ptr)
		{
			//转移权限
			ap._ptr = nullptr;
		}
		auto_ptr<T>& operator=(auto_ptr<T>& ap)
		{
			if (this != &ap)
			{
				if (_ptr)
				{
					delete _ptr;
				}
				_ptr = ap._ptr;
				ap._ptr = nullptr;
			}
			return *this;
		}
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
	};


	template<class T>
	class unique_ptr
	{
	public:
		unique_ptr(T* ptr)
			:_ptr(ptr)
		{

		}
		~unique_ptr()
		{
			if (_ptr)
				delete _ptr;
			std::cout << "~unique_ptr()" << std::endl;
		}
		unique_ptr(const unique_ptr<T>& ap) = delete;
		unique_ptr<T>& operator=(const unique_ptr<T>& ap) = delete;

		unique_ptr(unique_ptr<T>&& sp)
			:_ptr(sp._ptr)
		{
			sp._ptr = nullptr;
		}

		unique_ptr<T>& operator=(unique_ptr<T>&& sp)
		{
			delete _ptr;
			_ptr = sp._ptr;
			sp._ptr = nullptr;
		}
		
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;

	};


	template<typename T>
	class shared_ptr
	{
	public:
		explicit shared_ptr(T* ptr)
			:_ptr(ptr),
			 _pcount(new int(1))
		{
		}
		//特化带定制删除器
		template<class D>
		shared_ptr(T* ptr, D del)
			: _ptr(ptr)
			, _pcount(new int(1))
			, _del(del)
		{}
		~shared_ptr()
		{
			release();
		}
		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr),
			 _pcount(sp._pcount),
			 _del(sp._del)
		{
			++(*_pcount);
		}
		void release()
		{
			if (--(*_pcount) == 0)
			{
				// 最后⼀个管理的对象，释放资源
				_del(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}
		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			if (_ptr != sp._ptr)
			{
				release();
				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = sp._del;
			}
			return *this;
		}
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
		int* _pcount;
		//删除器
		std::function<void(T*)> _del = [](T* _ptr) {delete _ptr; };
	};

	template<class T>
	class weak_ptr
	{
	public:
		weak_ptr()
		{}
		weak_ptr(const shared_ptr<T>& sp)
			:_ptr(sp.get())
		{}
		weak_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();
			return *this;
		}
	private:
		T* _ptr = nullptr;
	};
}
